namespace RBAC.Write.Api.Application.Handler.BomHandler
{
    using System;
    using System.Data;
    using Dapper;
    using MediatR;
    using Microsoft.Extensions.Logging;
    using RBAC.Domain.BomManage;
    using RBAC.ErrorCode;
    using RBAC.Interstructrue.Base;
    using RBAC.Write.Api.Application.Command.BomCommand;

    /// <summary>
    /// 逻辑删除BOM（并删除关联的BomItem）处理器
    /// </summary>
    public class BomDeleteHandler : IRequestHandler<BomDeleteCommand, APIResult<int>>
    {
        private readonly IDbConnectionFactory _connectionFactory;
        private readonly ILogger<BomDeleteHandler> _logger;

        public BomDeleteHandler(IDbConnectionFactory connectionFactory, ILogger<BomDeleteHandler> logger)
        {
            _connectionFactory = connectionFactory;
            _logger = logger;
        }

        /// <summary>
        /// 使用数据库事务，逻辑删除BOM主表与其关联的明细表记录
        /// </summary>
        public async Task<APIResult<int>> Handle(BomDeleteCommand request, CancellationToken cancellationToken)
        {
            var result = new APIResult<int>();
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (request.Id <= 0)
                    return new APIResult<int> { Code = APIEnums.Fail, Msg = "参数无效：Id 必须大于 0", Data = 0 };

                using var connection = _connectionFactory.CreateConnectionWithRetry();
                using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);

                try
                {
                    // 1) 检查BOM是否存在且未删除
                    const string sqlCheck = "SELECT COUNT(1) FROM Bom WHERE Id = @Id AND IsDeleted = 0";
                    var exists = await connection.ExecuteScalarAsync<int>(new CommandDefinition(sqlCheck, new { request.Id }, transaction: transaction));
                    if (exists <= 0)
                    {
                        transaction.Rollback();
                        return new APIResult<int> { Code = APIEnums.Fail, Msg = "BOM不存在或已删除", Data = 0 };
                    }

                    // 2) 逻辑删除BOM主表
                    const string sqlDeleteBom = @"UPDATE Bom 
SET IsDeleted = 1
WHERE Id = @Id AND IsDeleted = 0";
                    var affectBom = await connection.ExecuteAsync(new CommandDefinition(sqlDeleteBom, new { request.Id }, transaction: transaction));

                    // 3) 逻辑删除关联的明细表 BomItem
                    const string sqlDeleteItems = @"UPDATE BomItem 
SET IsDeleted = 1
WHERE BomId = @Id AND IsDeleted = 0";
                    var affectItems = await connection.ExecuteAsync(new CommandDefinition(sqlDeleteItems, new { request.Id }, transaction: transaction));

                    // 提交事务
                    transaction.Commit();

                    result.Code = APIEnums.Success;
                    result.Msg = "删除成功";
                    result.Data = affectBom + affectItems; // 返回受影响行数总和
                }
                catch (OperationCanceledException)
                {
                    transaction.Rollback();
                    _logger?.LogWarning("删除BOM被取消");
                    result.Code = APIEnums.Fail;
                    result.Msg = "请求已取消";
                    result.Data = 0;
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    _logger?.LogError(ex, "删除BOM发生异常: {Message}", ex.Message);
                    result.Code = APIEnums.Fail;
                    result.Msg = "删除BOM异常: " + ex.Message;
                    result.Data = 0;
                }
            }
            catch (OperationCanceledException)
            {
                _logger?.LogWarning("删除BOM被取消");
                result.Code = APIEnums.Fail;
                result.Msg = "请求已取消";
                result.Data = 0;
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "删除BOM外层异常: {Message}", ex.Message);
                result.Code = APIEnums.Fail;
                result.Msg = "删除BOM异常: " + ex.Message;
                result.Data = 0;
            }

            return result;
        }
    }
}
